﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Stack
{
    public class Array<T>
    {
        private T[] data;
        private int size;
        public int DefaultDataLength = 10;

        /// <summary>
        /// 构造函数，传入数组的容量capacity构造Array
        /// </summary>
        /// <param name="capacity"></param>
        public Array(int capacity)
        {
            data = new T[capacity];
            size = 0;//此处的size表示数组中已经存放了多少个元素
        }

        /// <summary>
        /// 无参数的构造函数，默认数组的容量capacity=10
        /// </summary>
        public Array()
        {
            data = new T[DefaultDataLength];
            size = 0;
        }

        /// <summary>
        ///  获取数组的容量
        /// </summary>
        public int GetCapacity()
        {
            return data.Length;
        }

        /// <summary>
        ///  获取数组中的元素个数
        /// </summary>
        public int GetSize()
        {
            return size;
        }

        /// <summary>
        ///  返回数组是否为空
        /// </summary>
        public bool IsEmpty()
        {
            return size == 0;
        }


        // 向所有元素后添加一个新元素
        public void AddLast(T e)
        {
            //if (size == data.Length)
            //    throw new Exception("AddLast failed. Array is full.");

            //data[size] = e;
            //size++;
            Add(size, e);
        }

        // 在所有元素前添加一个新元素
        public void AddFirst(T e)
        {
            Add(0, e);
        }

        // 在index索引的位置插入一个新元素e
        public void Add(int index, T e)
        {
            if (size > data.Length || index < 0)
                throw new Exception("Add failed. Array is full.");
            if (size == data.Length)
                Resize(data.Length * 2);
            for (int i = size; i > index; i--)
                data[i] = data[i - 1];

            data[index] = e;

            size++;
        }

        // 通过索引删除元素
        public T Remove(int index)
        {
            T ret = data[index];
            for (int i = index + 1; i < size; i++)
                data[i - 1] = data[i];
            size--;
            if (size == data.Length / 2)
                Resize(data.Length / 2);
            return ret;
        }

        // 从数组中删除最后一个元素, 返回删除的元素
        public T RemoveLast()
        {
            return Remove(size - 1);
        }

        // 从数组中删除第一个元素, 返回删除的元素
        public T RemoveFirst()
        {
            return Remove(0);
        }

        // 从数组中删除元素e
        public void RemoveElement(T e)
        {
            int index = Find(e);
            if (index != -1)
                Remove(index);
        }

        //通过索引获取数据元素
        public T Get(int index)
        {
            return data[index];
        }

        //获取第一个元素
        public T GetFirst()
        {
            return Get(0);
        }

        //获取最后一个元素
        public T GetLast()
        {
            return Get(size - 1);
        }

        //通过索引给元素赋值
        public void Set(int index, T e)
        {
            data[index] = e;
        }

        //数组重置
        public void Clear(int capacity = 10)
        {
            data = new T[capacity];
            size = 0;
        }

        //获取所有的数组元素
        public override string ToString()
        {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.Append($"Array:size={size},capacity={data.Length}\r\n");
            stringBuilder.Append("[");
            for (int i = 0; i < size; i++)
                stringBuilder.Append(i != size - 1 ? data[i].ToString() + "," : data[i].ToString());
            stringBuilder.Append("]");
            return stringBuilder.ToString();
        }

        //判断数组中是否有该元素
        public bool Contains(T e)
        {
            for (int i = 0; i < size; i++)
            {
                if (data[i].Equals(e))
                    return true;
            }
            return false;
        }

        //查询值在数组中的位置
        public int Find(T e)
        {
            for (int i = 0; i < size; i++)
            {
                if (data[i].Equals(e))
                    return i;
            }
            return -1;
        }

        //自动扩容
        private void Resize(int NewCapacity)
        {
            T[] NewData = new T[NewCapacity];
            for (int i = 0; i < size; i++)
                NewData[i] = data[i];
            data = NewData;
        }

    }
}
